
#include "MHD_utils.h"
#include "MHD.h"
#define GET             0
#define POST            1

typedef struct connection_info_struct {
       int connectiontype;
       char *url;
       struct MHD_PostProcessor *postprocessor;
       char *post_data;
       char *request_mime_type;
	const char * method;
} con_info_t, *con_info_p;
     
        char *errorpage =
       "<html><body>This doesn't seem to be right.</body></html>";
	extern	mr_log_p MHD_log;
	extern	mr_conf_p pconf ;
	int MAXNAMESIZE,POSTBUFFERSIZE,MAXANSWERSIZE,MAXCLIENTS;
	struct MHD_Daemon *mhd;


static int answer_to_connection (void *cls,struct MHD_Connection *connection,
          const char *url,const char *method, const char *version,
          const char *upload_data, size_t *upload_data_size, void **con_cls );

static  void request_completed (void *cls, struct MHD_Connection *connection,
                        void **con_cls, enum MHD_RequestTerminationCode toe);

int iserver_init(int PORT){
	
	char * cMAXNAMESIZE , * cMAXANSWERSIZE,*cPOSTBUFFERSIZE
	,*cMAXCLIENTS;
	
	mr_conf_get(pconf,"www","MAXNAMESIZE",&cMAXNAMESIZE);
	mr_conf_get(pconf,"www","MAXANSWERSIZE",&cMAXANSWERSIZE);
	mr_conf_get(pconf,"www","POSTBUFFERSIZE",&cPOSTBUFFERSIZE);
	mr_conf_get(pconf,"www","MAXCLIENTS",&cMAXCLIENTS);

        MAXCLIENTS   = atoi(cMAXCLIENTS);
	MAXNAMESIZE    = atoi(cMAXNAMESIZE);
	MAXANSWERSIZE  = atoi(cMAXANSWERSIZE);
	POSTBUFFERSIZE = atoi(cPOSTBUFFERSIZE);
	mhd = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY,PORT
			, NULL, NULL,&answer_to_connection, NULL,
			MHD_OPTION_NOTIFY_COMPLETED, request_completed,                                 NULL, MHD_OPTION_END);
	if (NULL == mhd){
		printf("Error Start Daemon\n");
		mr_logger_write(MHD_log,LL_ERROR,
			"Error number 1 , Can't start daemon in MHD_init \n");
		return 1;
	}
	mr_logger_write(MHD_log,LL_INFO,"Start MHD Daemon\n ");
	return 0;
}
void iserver_close(){
 
	MHD_stop_daemon (mhd);

}
static int print_out_key (void *cls,
                enum MHD_ValueKind kind, const char *key,
                const char *value ){

        mr_logger_write(MHD_log,LL_TRACE, " %s : %s \n",key,value);
        return MHD_YES;
}

static int iterate_post (void *coninfo_cls, enum MHD_ValueKind kind,
		   const char *key,const char *filename, 
		   const char *content_type,const char *transfer_encoding, 
		   const char *data,
		   uint64_t off,
                   size_t size){
	 
	 mr_logger_write(MHD_log,LL_TRACE, "Iterate_post Respone : %s\n",data);
	 mr_logger_write(MHD_log,LL_TRACE, "Iterate_post Key : %s\n",key);
	 //con_info_p con_info = coninfo_cls;
	 return MHD_YES;
 }

static int handle_post(struct MHD_Connection *connection, con_info_p pcon ,const char *page) {

	int ret;
	struct MHD_Response *response=NULL;
	app_con_info_t appcon;
	memset(&appcon, 0, sizeof(appcon));
	if(NULL!=pcon)
	{
		if(NULL!=pcon->post_data)
		{
			mr_logger_write(MHD_log,LL_TRACE, 
					"post_data : %s\n",pcon->post_data);
				getMimeType(page,&(pcon->request_mime_type));
				appcon.url = pcon->url;
				appcon.post_data =pcon->post_data;
				appcon.request_mime_type =pcon->request_mime_type;
				appcon.connection =connection;
				appcon.method =pcon->method;	
				return handle_main_request(&appcon,MHD_log,pconf);
		}
	}
	if (!response){
		mr_logger_write(MHD_log,LL_TRACE, "Handle_post Respone : %s\n",
				pcon->post_data);
		return MHD_NO;
	}

	MHD_add_response_header (response, "Content-Type",
			pcon->request_mime_type);
	ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
	MHD_destroy_response (response);

	return ret;

}

static int answer_to_connection (void *cls,struct MHD_Connection *connection,
          const char *url,const char *method, const char *version,
          const char *upload_data, size_t *upload_data_size, void **con_cls ){
        
	mr_logger_write(MHD_log,LL_TRACE, "answe to connetion\n");
	con_info_p con_info = *con_cls;
	mr_logger_write(MHD_log,LL_TRACE, "############################\n");
	mr_logger_write(MHD_log,LL_TRACE, "url : %s\n",url);
	MHD_get_connection_values (connection, MHD_HEADER_KIND, 
			print_out_key,NULL);
	mr_logger_write(MHD_log,LL_TRACE, "############################\n");
	
	if (NULL == *con_cls)
	{
		mr_logger_write(MHD_log,LL_TRACE, "cls_null\n");
		con_info = malloc (sizeof (con_info_t));
		if (NULL == con_info)
			return MHD_NO;
		memset(con_info, 0, (sizeof (con_info_t)));
		con_info->url = strdup(url);
		con_info->method= method;     
		if (0 == strcmp (method, "POST"))
		{
			con_info->postprocessor =MHD_create_post_processor (
					connection,
					POSTBUFFERSIZE,
					iterate_post, (void *) con_info);
			con_info->connectiontype = POST;
		}
		else
			con_info->connectiontype = GET;
			*con_cls = (void *) con_info;
			return MHD_YES;
	}
     
       if (0 == strcmp (method, "POST"))
         {
		   if (*upload_data_size != 0)
		     {
				if( con_info->postprocessor ) {
					MHD_post_process(
							con_info->postprocessor,
							upload_data,
							*upload_data_size);
				}
				else 
				{
					con_info->post_data=strdup(upload_data);
				}
			       *upload_data_size = 0;
			       return MHD_YES;
		     }
		   else 
		   {
				if(con_info->post_data)
				{
					return handle_post(connection,con_info,
							&url[1]);
				}
		   }
	}
     
	if (0 == strcmp (method, "GET"))
         {
		
	   
		if(MHD_NO ==  html_file_return (connection, &url[1],MHD_HTTP_OK))
		{
		//	return handle_post(connection,con_info,&url[1]);
				mr_logger_write(MHD_log,LL_TRACE,
						"Get FileNotFound -> Rest API\n");
				app_con_info_t appcon;
				memset(&appcon, 0, sizeof(appcon));
				//getMimeType(&url[1],con_info->request_mime_type);
				appcon.url = url;
				//pappcon->post_data =pcon->post_data;
				//pappcon->request_mime_type =->request_mime_type;
				appcon.connection =connection;
				appcon.method =method;	
				return 	handle_main_request(&appcon,MHD_log,pconf);
		  	
		}else
		return MHD_YES;
         }
     
	return response_write(connection,"text/html",MHD_HTTP_OK,errorpage);
}

static void request_completed (void *cls, struct MHD_Connection *connection,
                        void **con_cls, enum MHD_RequestTerminationCode toe){
     			   
	con_info_p con_info = *con_cls;
     
	if (NULL == con_info)
		return;
	if (con_info->postprocessor)
	{
		MHD_destroy_post_processor (con_info->postprocessor);
	}
	if( con_info->post_data )
		free(con_info->post_data);
	
	if(con_info->url) free(con_info->url);
	
	free (con_info);
	*con_cls = NULL; 
}
